package com.qingcheng.task;

import com.alibaba.fastjson.JSON;
import com.qingcheng.dao.SeckillGoodsMapper;
import com.qingcheng.pojo.seckill.SeckillGoods;
import com.qingcheng.pojo.seckill.SeckillOrder;
import com.qingcheng.util.DateUtil;
import com.qingcheng.util.IdWorker;
import com.qingcheng.pojo.seckill.SeckillStatus;
import org.apache.ibatis.annotations.Param;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * 多线程异步操作类
 */
@Component
public class MultiThreadingCreateOrder {


    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;

    @Autowired
    private IdWorker idWorker;

    /**
     * 多线程下单操作
     * @Async 异步  run
     *
     */
    @Async
    public void createOrder(){
        try {
            System.out.println("----准备@Async执行-------");
            Thread.sleep(10000);

            //从队列中获取排队信息
            SeckillStatus seckillStatus = (SeckillStatus) redisTemplate.boundListOps("SeckillOrderQueue").rightPop();

            if(seckillStatus!=null) {

                //从商品库存对列中获取一个商品id
                Object goodsId = redisTemplate.boundListOps("SeckillGoodsCountList_"+seckillStatus.getTime()+"_"+seckillStatus.getGoodsId()).rightPop();
//                System.out.println(seckillStatus.getUsername()+goodsId+"++++++++++++++++++++++++++++++++++++++++++++");
                if(goodsId==null){
                    //情况当前用户的排队信息
                    clearQueue(seckillStatus);
                    return;
                }

                //时间区间
                String time = seckillStatus.getTime();
                //用户登录名
                String username = seckillStatus.getUsername();
                //用户抢购商品
                Long id = seckillStatus.getGoodsId();

                //获取商品信息
                SeckillGoods goods = (SeckillGoods) redisTemplate.boundHashOps("SeckillGoods_" + time).get(id);

//                Thread.sleep(20000);
                System.out.println(username+":"+Thread.currentThread().getId()+"---查询到的商品库存"+goods.getStockCount());

                if (goods != null && goods.getStockCount() > 0) {
                    //创建订单
                    SeckillOrder order = new SeckillOrder();
                    order.setId(idWorker.nextId());
                    order.setSeckillId(id);
                    order.setMoney(goods.getCostPrice());
                    order.setUserId(username);
                    order.setSellerId(goods.getSellerId());
                    order.setCreateTime(new Date());
                    order.setStatus("0");

                    //将秒杀订单存入到Redis中
                    redisTemplate.boundHashOps("SeckillOrder").put(username, order);

                    //库存减少
                    Long surplusCount = redisTemplate.boundHashOps("SeckillGoodsCount" + seckillStatus.getTime()).increment(goods.getId(), -1);

                    goods.setStockCount(surplusCount.intValue());
//                    goods.setStockCount(goods.getStockCount() - 1);

                    //判断当前商品是否还有库存
//                    if (goods.getStockCount() <= 0) {
                    if (surplusCount <= 0) {
                        //将商品数据同步到mysql数据中
                        seckillGoodsMapper.updateByPrimaryKeySelective(goods);
                        //清理redis缓存
                        redisTemplate.boundHashOps("SeckillGoods_" + time).delete(id);
                    } else {
                        //将数据同步到redis
                        redisTemplate.boundHashOps("SeckillGoods_" + time).put(id, goods);
                    }

                    //抢单成功，更新抢单状态->等待支付 更新抢单排队信息
                    // 1,抢单中...,2.抢单成功,3,支付超时,4.秒杀失败 5.支付完成
                    seckillStatus.setStatus(2);
                    seckillStatus.setOrderId(order.getId());
                    seckillStatus.setMoney(order.getMoney().floatValue());
                    redisTemplate.boundHashOps("UserQueueStatus").put(username,seckillStatus);

                    //发送rabbitMQ延时队列消息
                    sendDeplayMessage(seckillStatus);

                }
            }
            System.out.println("----开始执行-------");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 延时消息发送
     * @param seckillStatus
     */
    public void sendDeplayMessage(SeckillStatus seckillStatus){
        rabbitTemplate.convertAndSend("exchange.delay.order.begin",
                "delay",
                JSON.toJSONString(seckillStatus),
                new MessagePostProcessor() {
                    @Override
                    public Message postProcessMessage(Message message) throws AmqpException {
                        //延时队列，延时30分钟 ,如果此处设置的时间与配置中的队列时间冲突，以最小的为准,开发可以用10000毫秒
                        message.getMessageProperties().setExpiration(String.valueOf(1800000));
                        return message;
                    }
                });
    }

    /**
     * 清理用户排队信息  因为商品队列中没有剩余的库存,所以没有拿到库存的秒杀队列信息
     * @param seckillStatus
     */
    public void clearQueue(SeckillStatus seckillStatus) {

        //清理排队标识
        redisTemplate.boundHashOps("UserQueueCount").delete(seckillStatus.getUsername());

        //清理抢单标识
        redisTemplate.boundHashOps("UserQueueStatus").delete(seckillStatus.getUsername());

    }

}
